package com.hex.ds.hdrs.engine.service;

import com.hex.ds.hdrs.agent.service.AgentManager;
import com.hex.ds.hdrs.app.po.GroupConf;
import com.hex.ds.hdrs.app.service.AppManager;
import com.hex.ds.hdrs.center.service.CenterManager;
import com.hex.ds.hdrs.common.constant.ErrorCode;
import com.hex.ds.hdrs.common.exception.BizException;
import com.hex.ds.hdrs.common.utils.HdrsDateUtil;
import com.hex.ds.hdrs.common.utils.ListUtil;
import com.hex.ds.hdrs.engine.exec.DispatcherExec;
import com.hex.ds.hdrs.engine.manager.RunningManager;
import com.hex.ds.hdrs.engine.manager.ToDoManager;
import com.hex.ds.hdrs.engine.manager.ToRunManager;
import com.hex.ds.hdrs.period.task.service.TaskService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;


@Slf4j
@Service
public class DispatcherService {

    private static List<DispatcherExec> dispatcherThreadList = new ArrayList();

    @Autowired
    private CenterManager centerManager;
    @Autowired
    private AppManager appManager;
    @Autowired
    private AgentManager agentManager;
    @Autowired
    private TaskService taskService;
    @Autowired
    private ToDoManager toDoManager;
    @Autowired
    private ToRunManager toRunManager;
    @Autowired
    private RunningManager runningManager;
    @Autowired
    private ManagerService managerService;

    public ToRunManager getToRunManager() {
        return toRunManager;
    }

    public RunningManager getRunningManager() {
        return runningManager;
    }

    public ToDoManager getToDoManager() {
        return toDoManager;
    }

    public CenterManager getCenterManager() {
        return centerManager;
    }

    public AppManager getAppManager() {
        return appManager;
    }

    public AgentManager getAgentManager() {
        return agentManager;
    }

    public TaskService getTaskService() {
        return taskService;
    }

    public List<DispatcherExec> getThreadList() {
        return dispatcherThreadList;
    }

    /**
     * 初始化
     */
    public void init() {
        log.info("分发器初始化【DispatcherService.init】开始=======》");
        if (!ListUtil.isEmpty(dispatcherThreadList)) {
            log.warn("【警告】【DispatcherService.init】分发器线程集合不为空，清空线程集合………………");
            dispatcherThreadList.clear();
        }

        try {
            //创建线程池
            DispatcherExec dispatcherExec;
            List<GroupConf> groupList = appManager.getGroupList();
            for (GroupConf group : groupList) {
                String groupCode = group.getGroupCode();
                for (int i = 0; i < group.getThreadNum(); i++) {
                    dispatcherExec = new DispatcherExec(this,
                            "dispatcherExec-thread-" + groupCode + "-" + i, groupCode);
                    dispatcherThreadList.add(dispatcherExec);
                    dispatcherExec.start();
                }
            }
        } catch (Exception e) {
            log.error("分发器--初始化【DispatcherService.init】异常:{}", e.getMessage());
            dispatcherThreadList.clear();
            throw new BizException(ErrorCode.ERROR_810002);
        } finally {
            log.info("分发器--初始化【DispatcherService.init】结束《=======");
        }
    }

    public void addRefreshGroup(String groupCode, int num) {
        // 添加线程
        for (int i = 0; i < num; i++) {
            DispatcherExec dispatcherExec = new DispatcherExec(this,
                    "dispatcherExec-thread-" + groupCode + "-" + RandomUtils.nextInt(100, 1001), groupCode);
            dispatcherThreadList.add(dispatcherExec);
            dispatcherExec.start();
        }
    }

    /**
     * '
     *
     * @param newGroupConf
     * @return
     */
    public boolean refreshGroup(GroupConf newGroupConf) {
        String groupCode = newGroupConf.getGroupCode();
        log.info("刷新线程组【DispatcherService.refreshGroup】groupCode: {}", groupCode);
        try {
            List<GroupConf> groupList = appManager.getGroupList();
            List<String> codelist = new ArrayList();
            for (GroupConf group : groupList) {
                codelist.add(group.getGroupCode());
            }
            if (!codelist.contains(groupCode)) {
                // 添加线程
                for (int i = 0; i < newGroupConf.getThreadNum(); i++) {
                    DispatcherExec dispatcherExec = new DispatcherExec(this,
                            "dispatcherExec-thread-" + groupCode + "-" + RandomUtils.nextInt(100, 1001), groupCode);
                    dispatcherThreadList.add(dispatcherExec);
                    dispatcherExec.start();
                }
            } else {
                for (GroupConf group : groupList) {
                    if (newGroupConf.getGroupCode().equals(group.getGroupCode())) {
                        int srcThreadNum = group.getThreadNum();
                        int newThreadNum = newGroupConf.getThreadNum();
                        if (srcThreadNum == newThreadNum) {
                            return true;
                        } else if (srcThreadNum > newThreadNum) {
                            // 减少线程
                            this.closeThread(groupCode, srcThreadNum - newThreadNum);
                        } else {
                            // 添加线程
                            for (int i = srcThreadNum; i < newThreadNum; i++) {
                                DispatcherExec dispatcherExec = new DispatcherExec(this,
                                        "dispatcherExec-thread-" + groupCode + "-" + RandomUtils.nextInt(100, 1001), groupCode);
                                dispatcherThreadList.add(dispatcherExec);
                                dispatcherExec.start();
                            }
                        }
                        // 设置线程数
                        group.setThreadNum(newGroupConf.getThreadNum());
                    }
                }
            }

            return true;

        } catch (Exception e) {
            log.error("刷新线程组【DispatcherService.refreshGroup】异常:{}", e.getMessage());
            return false;
        }
    }


    /**
     * 减少线程数
     *
     * @param groupCode
     * @param num
     */
    public void closeThread(String groupCode, int num) {
        log.info("减少线程数【DispatcherService.closeThread】groupCode: {}, num: {}", groupCode, num);
        try {
            // 随机挑选减少的线程
            int closeNum = 0;
            List<DispatcherExec> closeList = new ArrayList();
            for (DispatcherExec dispatcherExec : dispatcherThreadList) {
                if (groupCode.equals(dispatcherExec.getGroupCode()) && closeNum < num) {
                    dispatcherExec.stopThread();
                    closeList.add(dispatcherExec);
                    closeNum++;
                }
            }

            //判断处理器的线程是否都执行完
            boolean flag = true;
            while (flag) {
                flag = false;
                for (DispatcherExec dispatcherExec : closeList) {
                    if (dispatcherExec.getRunningFlag()) {
                        flag = true;
                        break;
                    }
                }
                Thread.sleep(1000);
            }

            //关闭线程
            for (DispatcherExec dispatcherExec : closeList) {
                dispatcherExec.closeThread();
            }
        } catch (Exception e) {
            log.error("减少线程数【DispatcherService.closeThread】异常:{}", e.getMessage());
        }
        log.info("减少线程数【DispatcherService.closeThread】结束《=======");
    }

    /**
     * 暂停处理器
     */
    public void stopDispatcher() {
        log.debug("暂停分发器【DispatcherService.stopDispatcher】开始=====》【{}】", HdrsDateUtil.getCurTs());
        try {
            if (ListUtil.isEmpty(dispatcherThreadList)) {
                log.error("++++++【stopDispatcher】分发器线程为空++++++");
                return;
            }

            for (DispatcherExec dispatcherExec : dispatcherThreadList) {
                dispatcherExec.stopThread();
            }
            //判断处理器的线程是否都执行完
            boolean flag = true;
            while (flag) {
                flag = false;
                for (DispatcherExec dispatcherExec : dispatcherThreadList) {
                    if (dispatcherExec.getRunningFlag()) {
                        flag = true;
                        break;
                    }
                }
                Thread.sleep(1000);
            }
        } catch (Exception e) {
            log.error("暂停分发器【DispatcherService.stopProcess】异常: {}", e.getMessage());
        } finally {
            log.debug("暂停分发器【DispatcherService.stopDispatcher】结束《====【{}】", HdrsDateUtil.getCurTs());
        }
    }

    /**
     * 继续分发器
     */
    public void continueDispatcher() {
        log.debug("继续分发器【DispatcherService.continueDispatcher】开始==》");
        for (DispatcherExec dispatcherExec : dispatcherThreadList) {
            dispatcherExec.continueThread();
        }
        log.debug("继续分发器【DispatcherService.continueDispatcher】结束《==");
    }

    /**
     * 关闭处理器
     */
    public void closeDispatcher() {
        log.info("关闭处理器【DispatcherService.closeDispatcher】开始=======》");
        try {
            for (DispatcherExec dispatcherExec : dispatcherThreadList) {
                dispatcherExec.closeThread();
            }
            dispatcherThreadList.clear();
        } catch (Exception e) {
            log.error("关闭处理器【DispatcherService.closeDispatcher】异常:{}", e.getMessage());
        }
        log.info("关闭处理器【DispatcherService.closeDispatcher】结束《=======");
    }

}
